#include "stdafx.h"
#include "SelectReactor.h"

namespace Network
{
	SelectReactor::SelectReactor(EventDemultiplex* _demultiplexer) {
		handlers = (HandlerMap*)(malloc(sizeof(HandlerMap)));
		demultiplexer = _demultiplexer;
		handlers->count = 0;
	}

	SelectReactor::~SelectReactor() {
		free(handlers);	
	}

	void SelectReactor::register_handler(EventHandler* eventHandler){
		handlers->handlesArray[handlers->count] = eventHandler;
		++handlers->count;
	}

	void SelectReactor::remove_handler(EventHandler* eventHandler)	{
		for (int k = 0 ; k < handlers->count; ++k) {
			if (handlers->handlesArray[k]->getHandle().get_handle() == (eventHandler)->getHandle().get_handle()) { 
				handlers->handlesArray[k] = handlers->handlesArray[handlers->count];
				--handlers->count;
				return;
			}
		}
	}

	void SelectReactor::handle_events() {
		fprintf(stdout, "Waiting for events\n");
		
		while (true) {
			fd_set handles;
			handles.fd_count = handlers->count;
			//fprintf(stdout, "Handle count : %d\n", handlers->count);

			//update current fd_set array with currently existing handlers
			for (int k = 0; k < handlers->count;++k){
				handles.fd_array[k] = handlers->handlesArray[k]->getHandle().get_handle();
			}

			//wait on select()
			fd_set listeners = demultiplexer->Selects(handles);

			for (u_int i = 0; i < listeners.fd_count; ++i)	{
				int dataReceived = 0;
				char buffer[64];

				ZeroMemory(buffer, sizeof(buffer));

				SOCK_Stream stream;
				SOCK_Acceptor socket = SOCK_Acceptor(listeners.fd_array[i]);

				//Accept the connection from the socket stream
 				socket.accept(stream);
				fprintf(stdout, "Accepted connection from handler [0x%x]\n", socket.get_handle());

				stream.receive(buffer, 2, 0);

				// all messages have the following structure:
				// EventType	data[0]		-> type of event 
				// (u_char)		data[1]		-> size of the rest of the data structure
				// the handlers take care of parsing the rest of the message

				// find the event type to be able to select the correct handler
				EventType eventType = (EventType)(buffer[0]);

				// find the message size 
				u_int msgSize = buffer[1];
				char* message = (char*) malloc(sizeof(char)*msgSize);
				dataReceived = stream.receive(message,msgSize,0);

				// TODO concatenate buffer[0] and buffer[1] with char* message
				char* buf = (char*) malloc(sizeof(char)*msgSize + sizeof(buffer[0]) + sizeof(buffer[1]));				
				ZeroMemory(buf, sizeof(buf));
				buf[0] = buffer[0];
				buf[1] = buffer[1];

				for (u_int i = 0; i < (sizeof(char)*msgSize); i++) {
					buf[i+2] = message[i];
				}

				if (dataReceived == msgSize && dataReceived > 0) {
					for (int k = 0 ; k < handlers->count; ++k) {   
						//For all the handlers, check if they are of the given eventtype
						if (handlers->handlesArray[k]->getType()==eventType) {
							//Handle event
							handlers->handlesArray[k]->handle((unsigned char*)buf);
						}
					}
				} else {
					fprintf(stdout, "Error in receiving message from client \n");
				}
			}
		}
	}
}